// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// N [author] rhyme_lph
// W [email]  rhymelph@gmail.com
// R [github] https://github.com/rhymelph

import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/country_entity.dart';
import 'package:finance_app/src/entities/employee_contact_entity.dart';
import 'package:finance_app/src/http_service/http_employee_contact_service.dart';
import 'package:finance_app/src/mixin/check_plan_mixin.dart';
import 'package:finance_app/src/mixin/init_edit_data_mixin.dart';
import 'package:finance_app/src/provider/hr_payroll/employee/views/employee_other_provider.dart';
import 'package:finance_app/src/provider/hr_payroll/employee/views/employee_provider.dart'
    as e;
import 'package:finance_app/src/provider/hr_payroll/employee/views/particulars_provider.dart';
import 'package:finance_app/src/provider/hr_payroll/hr_and_payroll_provider.dart';
import 'package:finance_app/src/provider/hr_payroll/views/employee_provider.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/utils/date_time_utils.dart';
import 'package:finance_app/src/utils/permission_utils.dart';
import 'package:finance_app/src/widgets/bottom_sheet/date_time_select_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/got_it_tip_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/normal_info_bottom_sheet.dart';
import 'package:flutter/material.dart';

class NewEmployeeProvider extends BaseProvider<EmployeeContactEntity>
    with InitEditDataMixin<EmployeeContactEntity>, CheckPlanMixin {
  List<String> menuList = [
    'Edit',
    'Mark As Resigned',
  ];

  int userId;

  @override
  Future get dataFuture =>
      id != null ? HttpEmployeeContactService.showContact(id) : null;

  @override
  List<BaseProvider> registerChildProviders() => [
        ParticularsProvider(),
        EmployeeOtherProvider(),
        e.EmployeeProvider(),
      ];

  void initData(EmployeeContactEntity entity, bool isDuplicate) {
    final employee = getChildProvider<e.EmployeeProvider>();
    final other = getChildProvider<EmployeeOtherProvider>();
    if (entity == null) {
      employee.leaveList.add(EmployeeContactLeaveData()
        ..name = Config.settingData.leaveType.first.key
        ..amount = 0);
      other.country = Config.defaultCountry;
      return;
    }
    if (isDuplicate != true) {
      init(entity.id);
    }
    final particular = getChildProvider<ParticularsProvider>();
    particular.nameController.text = entity.name;
    particular.birthDate = DateTimeUtils.toDateTime(entity.dob, 'yyyy-MM-dd');
    particular.gender = entity.genderName;
    particular.employeeIdController.text = entity.employeeNumber;
    particular.race = entity.race;
    particular.maritalStatus = Config.settingData.martialStatus?.firstWhere(
        (element) => element.key == entity.martialStatus,
        orElse: () => null);
    particular.passType = Config.settingData.passType?.firstWhere(
        (element) => element.key == entity.passType,
        orElse: () => null);
    particular.nricController.text = entity.identityNumber;
    particular.nationality = Config.settingData.country?.firstWhere(
        (element) => element.name == entity.nationality,
        orElse: () => CountryEntity()..name = entity.nationality);
    userId = entity.userId;
    particular.nricController.text = entity.identityNumber;
    particular.passIssueDate =
        DateTimeUtils.toDateTime(entity.identityIssuedAt, 'yyyy-MM-dd');
    particular.passExpiryDate =
        DateTimeUtils.toDateTime(entity.identityExpireAt, 'yyyy-MM-dd');
    particular.prStart =
        DateTimeUtils.toDateTime(entity.prStartedAt, 'yyyy-MM-dd');
    employee.employeeIdController.text = entity.employeeNumber;
    employee.jobTitleController.text = entity.title;
    employee.workingDaysCount = entity.workingDaysCount;
    employee.workingDays = entity.workingDays;
    employee.foreignLevyController.text = entity.workerLevy;
    employee.employmentType = Config.settingData.employmentType?.firstWhere(
        (element) => element.key == entity.employmentType,
        orElse: () => null);
    employee.salaryPeriod = Config.settingData.salaryPeriod?.firstWhere(
        (element) => element.key == entity.salaryPeriod,
        orElse: () => null);
    employee.salaryList.clear();
    if (entity.incomeData != null) {
      for (final item in entity.incomeData) {
        employee.salaryList.add({
          'title': item.name,
          'controller': TextEditingController(
              text: item.amount != null && item.amount != 0
                  ? item.amount.toStringAsFixed(2)
                  : null),
          'focusNode': FocusNode(),
          'currency': item.currencyCode ?? 'SGD',
          'cpfPayable': item.cpfPayable,
          "wageType": item.wageType,
        });
      }
    }
    if (entity.contributionAmount != null)
      employee.shgAmount = double.parse(entity.contributionAmount);
    employee.selfHelpGroup = Config.settingData.contribution.firstWhere(
        (element) => element.key == entity.contribution,
        orElse: () => null);
    employee.deductionList = entity.deductionData;
    // employee.selfHelpGroup = entity.confirmedAt;
    employee.hiredDate =
        DateTimeUtils.toDateTime(entity.joinedAt, 'yyyy-MM-dd');
    employee.confirmationDate =
        DateTimeUtils.toDateTime(entity.confirmedAt, 'yyyy-MM-dd');
    // employee.selfHelpGroup =entity.gr
    employee.leaveList = entity.leaveData;

    if (entity.isDirector == 1) {
      employee.currentSelectEmployeeType = S.current.company_director;
    } else {
      employee.currentSelectEmployeeType = S.current.employee;
    }
    employee.selfHelpGroup = Config.settingData.contribution.firstWhere(
        (element) => element.key == entity.contribution,
        orElse: () => null);

    other.countryCode = entity.countryCode;
    other.country = Config.settingData.country.firstWhere(
        (element) => element.name == entity.addressCountry,
        orElse: () => null);

    other.address = entity.addressLine1;
    other.unitNumberController.text = entity.addressUnit;
    other.postalCodeController.text = entity.addressPostalCode;
    other.contactNameController.text = entity.emergencyContactName;
    other.relationshipController.text = entity.emergencyContactRelationship;
    other.phoneNumberController.text = entity.phoneNumber;
    other.contactPhoneNumberController.text =
        entity.emergencyContactPhoneNumber;
    other.contactCountryCode = entity.emergencyContactCountryCode;
    other.bankController.text = entity.bankName;
    //缺少
    // other.bankCodeController.text = entity.bankBranchCode;
    other.accountHolderNameController.text = entity.bankAccountName;
    other.accountNumberController.text = entity.bankAccountNumber;
    other.branchCodeController.text = entity.bankBranchCode;
    other.bankCodeController.text = entity.bankCode;

    if (!Config.hasPermission(PermissionUtils.hrPayroll)) {
      menuList = [];
    }
  }

  void onChange(TabController tabController) {}

  void onSave() async {
    final particular = getChildProvider<ParticularsProvider>();
    final employee = getChildProvider<e.EmployeeProvider>();
    final other = getChildProvider<EmployeeOtherProvider>();
    particular.unFocus();
    employee.unFocus();
    other.unFocus();

    String name = particular.nameController.text;
    String title = employee.jobTitleController.text;
    String nationality = particular.nationality?.key;
    String race = particular.race;
    String martialStatus = particular.maritalStatus?.key;
    String passType = particular.passType?.key;
    // String pr_started_at = particular;
    String gender = particular.gender != null
        ? particular.gender == 'Female'
            ? 'F'
            : 'M'
        : null;
    String dob =
        DateTimeUtils.formatDateTime(particular.birthDate, 'yyyy-MM-dd');

    String identityNumber = particular.nricController.text;
    String employeeNumber = particular.employeeIdController.text;
    if (employeeNumber.isEmpty) {
      employeeNumber = employee.employeeIdController.text;
    }
    String workerLevy = employee.foreignLevyController.text;
    String employmentType = employee.employmentType?.key;
    String salaryPeriod = employee.salaryPeriod?.key;
    String contribution = employee.selfHelpGroup?.key;
    double contributionAmount = employee.shgAmount;
    if (employee.salaryList == null) employee.salaryList = [];

    List incomeData = employee.salaryList
        .map((e) => {
              'name': e['title'],
              'currency_code': employee.salaryList.first['currency'],
              'amount': double.parse(e['controller'].text, (e) => null),
              'cpf_payable': e['cpfPayable'],
              "wage_type": e['wageType'],
            })
        .toList();

    if (employee.deductionList == null) employee.deductionList = [];

    List deductionData = employee.deductionList
        .map((e) => {
              'name': e.name,
              'currency_code': employee.salaryList.first['currency'],
              'amount': e.amount,
            })
        .toList();

    if (employee.leaveList == null) employee.leaveList = [];

    List leaveData = employee.leaveList
        .map((e) => {
              'name': e.name,
              'amount': e.amount,
            })
        .toList();

    List workingDayData = employee.workingDays
        .map((e) => {
              'is_working': e.isWorking,
              'is_half_day': e.isHalfDay,
            })
        .toList();

    // Map<int, dynamic> workingDayData = Map();
    // employee.workingDays.asMap().forEach((key, workingDay) {
    //   workingDayData.putIfAbsent(
    //       key,
    //       () => {
    //             'is_working': workingDay.isWorking,
    //             'is_half_day': workingDay.isHalfDay
    //           });
    // });

    String joinedAt =
        DateTimeUtils.formatDateTime(employee.hiredDate, 'yyyy-MM-dd');
    String confirmedAt =
        DateTimeUtils.formatDateTime(employee.confirmationDate, 'yyyy-MM-dd');
    String countryCode = other.countryCode;
    String phoneNumber = other.phoneNumberController.text;
    // String email = other
    int isDirector =
        employee.currentSelectEmployeeType == S.current.employee ? 0 : 1;

    String addressCountry = other.country?.key;

    String addressPostalCode = other.postalCodeController.text;
    String addressLine1 = other.address;
    String addressUnit = other.unitNumberController.text;

    String emergencyContactName = other.contactNameController.text;
    String emergencyContactRelationship = other.relationshipController.text;
    String emergencyContactCountryCode = other.contactCountryCode;
    String emergencyContactPhoneNumber =
        other.contactPhoneNumberController.text;

    String bankAccountName = other.accountHolderNameController.text;
    String bankAccountNumber = other.accountNumberController.text;
    String bankName = other.bankController.text;
    String bankCode = other.bankCodeController.text;
    String bankBranchCode = other.branchCodeController.text;
    String identityIssuedAt =
        DateTimeUtils.formatDateTime(particular.passIssueDate, 'yyyy-MM-dd');
    String identityExpireAt =
        DateTimeUtils.formatDateTime(particular.passExpiryDate, 'yyyy-MM-dd');
    // if (particular.passType?.name != null &&
    //     particular.passType.name.startsWith('Foreigner')) {
    // } else {}
    String prStartTime =
        DateTimeUtils.formatDateTime(particular.prStart, 'yyyy-MM-dd');

    EmployeeContactEntity dataResult;

    //todo 界面上没有 email address_city
    //todo 返回的数据为500
    if (isEdit == true) {
      await post(
          HttpEmployeeContactService.updateContact(
            id,
            identity_issued_at: identityIssuedAt,
            identity_expire_at: identityExpireAt,
            name: name,
            title: title,
            nationality: nationality,
            race: race,
            martial_status: martialStatus,
            pass_type: passType,
            pr_started_at: prStartTime,
            gender: gender,
            dob: dob,
            identity_number: identityNumber,
            employee_number: employeeNumber,
            employment_type: employmentType,
            salary_period: salaryPeriod,
            contribution: contribution,
            contribution_amount: contributionAmount,
            income_data: incomeData,
            deduction_data: deductionData,
            leave_data: leaveData,
            working_days: workingDayData,
            working_days_count: employee.workingDaysCount,
            worker_levy: workerLevy,
            joined_at: joinedAt,
            confirmed_at: confirmedAt,
            country_code: countryCode,
            phone_number: phoneNumber,
            // email: email,
            is_director: isDirector,
            address_country: addressCountry,
            // address_city:  adderss_city,
            address_postal_code: addressPostalCode,
            address_line_2: addressLine1,
            address_line_1: addressLine1,
            address_unit: addressUnit,
            emergency_contact_name: emergencyContactName,
            emergency_contact_relationship: emergencyContactRelationship,
            emergency_contact_phone_number: emergencyContactPhoneNumber,
            emergency_contact_country_code: emergencyContactCountryCode,
            bank_account_name: bankAccountName,
            bank_account_number: bankAccountNumber,
            bank_name: bankName,
            bank_code: bankCode,
            bank_branch_code: bankBranchCode,
          ),
          autoHandler: AutoHandler.Toast,
          loadingTip: S.current.loading, onSuccess: (result) {
        dataResult = getEntityFromResult<EmployeeContactEntity>(result);
      });
    } else {
      await post(
          HttpEmployeeContactService.createEmployee(
            identity_issued_at: identityIssuedAt,
            identity_expire_at: identityExpireAt,
            name: name,
            title: title,
            nationality: nationality,
            race: race,
            martial_status: martialStatus,
            pass_type: passType,
            pr_started_at: prStartTime,
            gender: gender,
            dob: dob,
            identity_number: identityNumber,
            employee_number: employeeNumber,
            employment_type: employmentType,
            salary_period: salaryPeriod,
            contribution: contribution,
            contribution_amount: contributionAmount,
            income_data: incomeData,
            deduction_data: deductionData,
            leave_data: leaveData,
            working_days: workingDayData,
            working_days_count: employee.workingDaysCount,
            worker_levy: workerLevy,
            joined_at: joinedAt,
            confirmed_at: confirmedAt,
            country_code: countryCode,
            phone_number: phoneNumber,
            // email: email,
            is_director: isDirector,
            address_country: addressCountry,
            // address_city:  adderss_city,
            address_postal_code: addressPostalCode,
            address_line_2: addressLine1,
            address_line_1: addressLine1,
            address_unit: addressUnit,
            emergency_contact_name: emergencyContactName,
            emergency_contact_relationship: emergencyContactRelationship,
            emergency_contact_phone_number: emergencyContactPhoneNumber,
            emergency_contact_country_code: emergencyContactCountryCode,
            bank_account_name: bankAccountName,
            bank_account_number: bankAccountNumber,
            bank_name: bankName,
            bank_code: bankCode,
            bank_branch_code: bankBranchCode,
          ),
          autoHandler: AutoHandler.Toast,
          loadingTip: S.current.loading, onSuccess: (result) {
        dataResult = getEntityFromResult<EmployeeContactEntity>(result);
      });
    }
    if (dataResult != null) {
      Providers.get<HrAndPayrollProvider>(
              RouterGenProviders.hrAndPayrollPage, null)
          ?.getChildProvider<EmployeeProvider>()
          ?.updateEmployee(dataResult);
      if (!Config.hasPermission(PermissionUtils.homeDashboard))
        Config.dashboardProvider
            ?.getChildProvider<HrAndPayrollProvider>()
            ?.getChildProvider<EmployeeProvider>()
            ?.updateEmployee(dataResult);

      obtainContext?.call((context) {
        Navigator.of(context).pop(dataResult);
      });
    }
  }

  void onSelectMenu(String value) {
    switch (value) {
      case 'Edit':
        onChangeEditMode();
        break;
      case 'Mark As Resigned':
        _onMarkAsResigned();
        break;
    }
  }

  void _onMarkAsResigned() {
    if (isPlanExpired()) return;
    obtainContext?.call((context) async {
      DateTime selectDateTime = await showDateTimeSelectBottomSheet(
          context, 'Resignation Date', null,
          withinFinancialYear: false);
      if (selectDateTime != null) {
        bool isSuccess = await showEmployeeMarkAsResignedNormalInfoBottomSheet(
            context,
            dateTime: selectDateTime);
        if (isSuccess == true) {
          isSuccess = false;
          String resignedDate =
              DateTimeUtils.formatDateTime(selectDateTime, 'yyyy-MM-dd');

          await post(HttpEmployeeContactService.resignContact(id, resignedDate),
              autoHandler: AutoHandler.Toast,
              loadingTip: 'Loading', onSuccess: (result) {
            isSuccess = true;
          });
          if (isSuccess) {
            // data = await transformData(data, false);
            // update();
            await showEmployeeMarkResignedSuccessBottomSheet(context);
            Providers.get<HrAndPayrollProvider>(
                    RouterGenProviders.hrAndPayrollPage, null)
                ?.getChildProvider<EmployeeProvider>()
                ?.updateResigned(id, resignedDate);
            if (!Config.hasPermission(PermissionUtils.homeDashboard))
              Config.dashboardProvider
                  ?.getChildProvider<HrAndPayrollProvider>()
                  ?.getChildProvider<EmployeeProvider>()
                  ?.updateResigned(id, resignedDate);
            Navigator.of(context).pop();
          }
        }
      }
    });
  }

  @override
  Future get editDataFuture => dataFuture;

  @override
  TextEditingController get numberCtl =>
      getChildProvider<e.EmployeeProvider>().employeeIdController;

  @override
  String get type => 'employee';

  @override
  FutureOr<EmployeeContactEntity> transformData(
      EmployeeContactEntity d, bool isCache) {
    initData(d, false);
    return super.transformData(d, isCache);
  }
}
